ci(claude): allow fork-PR authors to trigger Claude review#932
Conversation
The claude-code-action gates execution on the actor's repo permission. Fork PR authors only have read, so the action exits with "Actor does not have write permissions to the repository" before ever calling Anthropic. Setting allowed_non_write_users: "*" on pr-review and issue-handler bypasses that gate so external contributors get the same auto-review maintainers do, without having to maintain a username allowlist. Skipped pr-comment (already filtered to non-fork PRs) and release-notes (only fires from a maintainer-owned tag push). Header comment documents the residual prompt-injection risk and the action's built-in mitigations (subprocess secret scrubbing, pinned bun, hardened PATH) so future-us knows what to tighten if a real exfiltration attempt lands.
SummarySurgical 3-hunk change adding Issues Found🟡 Important —
|
## Why this matters v0.18.0 ships agent memory v2 (hybrid-search second brain with LLM extraction and observability dashboard), ChatAgent split into three composable agents (Chat/FileIO/DocumentQA), parallel tool calls, and a Telegram adapter scaffold — plus fixes the RAG-on-PDF timeout with Gemma 4 that broke document Q&A since v0.17.6 and adds CI gates that enforce RAG quality baselines on every future PR. Full notes: `docs/releases/v0.18.0.mdx`. ## What's New - **Agent memory v2** ([amd#606](amd#606)) — Hybrid semantic + keyword search, LLM extraction, observability dashboard via SSE streaming ([amd#1032](amd#1032)). Per-user isolation enforced; extraction runs async so it doesn't add latency. - **ChatAgent split** ([amd#979](amd#979)) — `ChatAgent`, `FileIOAgent`, and `DocumentQAAgent` replace the monolithic class; each composable via `tools=`. Backward-compatible shim preserved. - **Parallel tool calls** ([amd#946](amd#946)) — Multiple `tool_calls` from a single LLM turn are executed concurrently, cutting round-trips for multi-tool workflows. - **Telegram adapter scaffold, Phase 0** ([amd#951](amd#951)) — `gaia telegram start|stop|status`, per-user session isolation, `[telegram]` extras. Phase 1 (message handling + allowed-users gate) tracked in [amd#889](amd#889). - **Connectors: per-MCP toggle + single-writer enforcement** ([amd#1018](amd#1018), [amd#998](amd#998)) — Disable individual MCP servers without removing them; concurrent writes serialised with actionable errors on contention. - **File navigation, web browsing, and write security** ([amd#495](amd#495)) — `FileSearchToolsMixin`, web browsing tool, and scratchpad mixin in `KNOWN_TOOLS`; write tools check `allowed_paths` before dispatch. - **Email UI and policy alerts** ([amd#995](amd#995), [amd#1039](amd#1039), [amd#952](amd#952)) — Pre-scan triage card, in-chat Connect, policy alert cards, and durable receipts for confirmation-gated actions. ## Bug Fixes - **RAG-on-PDF timeouts on Gemma 4** ([amd#1034](amd#1034), closes [amd#1030](amd#1030)) — Prompt-size budget check added at composition time; CI gates enforce it on every PR ([amd#1040](amd#1040)). - **Envelope-level parse failure crashed SD recovery** ([amd#1047](amd#1047), closes [amd#1023](amd#1023)) — Falls through to a clean recovery path with step-1 context preserved. - **Windows-path tool args corrupted** ([amd#1027](amd#1027)) — Backslash normalisation now happens after argument parsing. - **Blender `send_command` hung** ([amd#1026](amd#1026), closes [amd#1022](amd#1022)) — Read timeout applied to persistent-connection servers. - **`gaia chat init` in post-install banner** ([amd#1029](amd#1029), closes [amd#1024](amd#1024)) — Replaced with the correct `gaia init`. - **Keyring treated as required** ([amd#1028](amd#1028)) — Import guarded; optional on systems without `keyring`. - **electron-builder URLs stale** ([amd#953](amd#953)) — Three doc/installer files updated to current download paths. ## Tooling & Docs - **RAG eval CI gates** ([amd#1040](amd#1040), closes [amd#1033](amd#1033)) — RAG quality baselines + prompt-size budget enforced on every PR. - **Fork-PR authors now receive Claude review** ([amd#932](amd#932)) — `allowed_non_write_users: "*"` with prompt-injection mitigations documented. - **Eval runs mandated before merging** ([amd#1036](amd#1036)) — `CLAUDE.md` requires `gaia eval agent` for LLM-affecting changes. - **GAIA website** ([amd#369](amd#369)) — [amd-gaia.ai](https://amd-gaia.ai) live. - **Custom agent guide reorganised** ([amd#997](amd#997)), Lemonade PPA docs ([amd#801](amd#801)), broken Lemonade CLI URL fixed ([amd#996](amd#996)), WhatsApp adapter evaluation spec ([amd#950](amd#950)). ## Release checklist - [x] `util/validate_release_notes.py docs/releases/v0.18.0.mdx --tag v0.18.0` passes - [x] `src/gaia/version.py` → `0.18.0` - [x] `src/gaia/apps/webui/package.json` → `0.18.0` - [x] Navbar label in `docs/docs.json` → `v0.18.0 · Lemonade 10.2.0` - [x] All 28 commits in range (v0.17.6..HEAD) are represented in the notes - [ ] Review from @kovtcharov-amd addressed
Summary
The
claude-code-actiongates execution on the actor's repo permission. Fork-PR authors only haveread, so the action exits with"Actor does not have write permissions to the repository"before ever calling Anthropic — which is why PR #924 from@theonlychant(and any future fork PR) gets a 5-second red ❌ on the Claude AI Assistant check. Settingallowed_non_write_users: "*"onpr-reviewandissue-handlerbypasses that gate so external contributors get the same auto-review maintainers do, with no username allowlist to maintain.Threads
pr-review+issue-handlergetallowed_non_write_users: "*"— these are the two jobs that take input from non-maintainers (fork-PR diffs,@claudementions on issues / PR conversations).pr-commentandrelease-notesleft alone —pr-commentis already filtered to non-fork PRs (head.repo.full_name == github.repository), andrelease-notesonly fires from a maintainer-owned tag push viaworkflow_run. The actor on those is always a write user, so the gate is a no-op there.Bashin--allowedToolsand access toANTHROPIC_API_KEY+GITHUB_TOKEN. Prompt injection in the diff could try to coerce Claude into running an exfiltration command. The action's built-in mitigations (subprocess secret scrubbing viaCLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1auto-set when this input is non-empty, pinned bun binary, hardened PATH) reduce — but don't eliminate — the surface. Future-us reading the header knows what to tighten if a real attempt lands (swap*for a literal username list — verified upstream insrc/github/validation/permissions.tsthatallowed_non_write_usersonly takes literal usernames or*, notauthor_associationvalues likeCONTRIBUTOR).Test plan
pull_request_targetuses the workflow frommain, not the PR head, so this PR can't validate itself. The verification path is post-merge:main⚠️ SECURITY WARNING: Bypassing write permission check for theonlychant due to allowed_non_write_users configuration(the action emits this when the bypass takes effect)pr-comment(non-fork-only) still works on a maintainer's@claudereview-comment replyCloses #1053